import LevelScene from "../LevelScene";
import { TButton, DirectionCode, KeyEventParameters, MoveInfo, FingerStyle, SceneState } from "../SceneControl";
import UIMrg from "../../Script/UIMrg";
import BattlePanel from "../../Script/BattlePanel";

const { ccclass, property } = cc._decorator;

export default abstract class HandGridMoveScene extends LevelScene {

    /**
     * 节点网格，二维数组结构，用于存储场景中的节点。
     * 每个元素代表一个节点，通过二维坐标可以定位到具体的节点。
     */
    nodeGrid: cc.Node[][];

    /**
     * 当前选中节点在 nodeGrid 中的位置，使用二维向量表示。
     * 初始值为 (0, 0)，表示默认选中网格中的第一个节点。
     */
    currSite: cc.Vec2;

    /**
     * 战斗面板实例，用于访问和操作战斗面板相关的数据和功能。
     * 由于类型为 any，实际使用时需要注意类型安全。
     */
    BattlePanel: any;

    /**
     * 合并面板实例，用于访问和操作合并面板相关的数据和功能。
     * 由于类型为 any，实际使用时需要注意类型安全。
     */
    MergePanel: any;

    /**
     * 网格数据，二维数组结构，每个元素包含一个 _view 属性，该属性为一个节点。
     * 通常用于表示场景中的网格布局信息。
     */
    grids: {
        enabled: any;
        _view: cc.Node
    }[][];

    /**
     * 物品列表，数组结构，每个元素包含物品的数据、是否正在拖拽的状态以及对应的节点视图。
     */
    items: {
        /** 物品的数据，具体内容根据实际需求而定 */
        data: any;
        /** 物品是否正在被拖拽的状态标识 */
        isDraging: boolean;
        /** 物品对应的节点视图 */
        _view: cc.Node
    }[];

    /**
     * 按钮列表，数组结构，存储场景中的按钮节点。
     */
    buttons: cc.Node[];

    /**
     * 底部 UI 节点，用于存储底部的 UI 元素。
     */
    bottomUi: cc.Node;


    onlyGrid: boolean = false;
    showOrHide: cc.Node;
    firstNode: cc.Node;

    /**
     * 当节点启用时触发的生命周期方法
     * 该方法会执行场景初始化、事件监听绑定、获取面板数据等操作
     */
    protected onEnable(): void {
        // 调用父类的 onEnable 方法
        super.onEnable();
        // 初始化场景
        this.initScene();
    }

    public startScene() {
        this.currSite = cc.v2(0, 0);
        // 初始化节点网格，初始值为包含当前节点的二维数组
        this.nodeGrid = [[this.node]]
        // 监听当前节点的位置变化事件，当位置变化时调用 resetBtnPos 方法
        this.node.on(cc.Node.EventType.POSITION_CHANGED, this.resetBtnPos, this);
        // 通过 UIMrg 获取 BattlePanel 实例
        this.BattlePanel = UIMrg.UIMrg.getPanel(BattlePanel.BattlePanel);
        // 从 BattlePanel 的 _merge 属性中获取网格数据
        this.grids = this.BattlePanel._merge._grids;
        // 从 BattlePanel 的 _merge 属性中获取物品数据

        // 将 grids 中的每个 item 的 _view 提取出来，组成新的二维节点数组
        this.nodeGrid = this.grids.map((grid) => {
            return grid.map((item) => {
                return item._view;
            });
        });

        if (!this.onlyGrid) {
            this.items = this.BattlePanel._merge._items;
            // 从 BattlePanel 的视图中查找 merge/bottom 节点
            this.bottomUi = cc.find("merge/bottom", this.BattlePanel._view);

            this.showOrHide = cc.find("showOrHide", this.bottomUi);
            // 从 bottomUi 节点中查找 buttons 节点，并获取其所有子节点
            this.buttons = cc.find("buttons", this.bottomUi).children.concat();
            // 将 items 中的每个 item 的 _view 提取出来，作为一个新的节点数组添加到 nodes 中
            this.nodeGrid.push(this.items.map((item) => {
                return item._view;
            }));

            // 将 buttons 数组添加到 nodes 中
            this.nodeGrid.push(this.buttons);
            // 初始化第一个选中的节点位置，传入第一个物品的视图节点
            this.setSiteByNode(this.items[0]._view);

            this.tscene.sceneState = SceneState.stop;
            this.tscene.apply();

            this.showOrHide.on("active-in-hierarchy-changed", () => {
                if (this.showOrHide.activeInHierarchy) {
                    this.tscene.sceneState = SceneState.normal;
                    this.tscene.apply();
                    this.resetBtnPos();
                } else {
                    this.tscene.sceneState = SceneState.stop;
                    this.tscene.apply();
                }
            }, this);
        }

        // 重置按钮位置
        this.resetBtnPos();
    }

    protected onDisable(): void {
        super.onDisable();
        this.currSite = null;
        this.nodeGrid = null;
        this.items = null;
        this.buttons = null;
        this.bottomUi = null;
        this.node.off(cc.Node.EventType.POSITION_CHANGED, this.resetBtnPos, this);
        this.handNode.targetOff(this);
        this.showOrHide && this.showOrHide.targetOff(this);
        if (this.catchNode) {
            this.catchNode = null;
            this.stopHandCatchingAction();
            this.playHandLoosenAnim(() => {
                this.playHandBreathingAnim();
            });
        }
    }

    protected initBtn(): void {
        this.btn = new TButton(this.node, [DirectionCode.BACK]);
        let lastPos: cc.Vec2 | null = null;

        // 提取方向键判断逻辑
        const isDirectionKey = (code: DirectionCode) => [
            DirectionCode.LEFT,
            DirectionCode.RIGHT,
            DirectionCode.UP,
            DirectionCode.DOWN
        ].includes(code);

        // 提取触发触摸移动事件的逻辑
        const triggerTouchMoveEvent = () => {
            if (this.catchNode) {
                const handSite: cc.Vec2 = this.handNode.convertToWorldSpaceAR(cc.Vec2.ZERO);
                if (!lastPos) lastPos = cc.v2(handSite.x, handSite.y);
                const touchEvent = this.getTouchEvent(cc.Node.EventType.TOUCH_MOVE);
                this.catchNode.dispatchEvent(touchEvent);
            }
        };

        this.btn.addKeyDownEvent((para: KeyEventParameters) => {
            if (this.levelStop) return;
            if (isDirectionKey(para.DirectionCode)) {
                this.moveButton(para.DirectionCode);
                if (this.catchNode) {
                    triggerTouchMoveEvent();
                }
                this.stopHandCatchingAction();
            } else if (para.DirectionCode === DirectionCode.ENTER) {
                if (this.catchNode) {
                    this.catchNode.dispatchEvent(this.getTouchEvent(cc.Node.EventType.TOUCH_END));
                    this.stopHandCatchingAction();
                    this.catchNode = null;
                    this.startLocation = null;
                    this.playHandLoosenAnim(() => {
                        this.playHandBreathingAnim();
                    });
                    return;
                } else {
                    this.levelStop = true;
                    this.playHandCatchAnim(() => {
                        this.levelStop = false;
                        if (this.catchNode) {
                            this.playHandCatchingAction();
                        } else {
                            this.playHandLoosenAnim(() => {
                                this.stopHandCatchingAction();
                                this.playHandBreathingAnim();
                            });
                        }
                    });
                    this.addBtnEventKeyDown(para);
                    if (this.catchNode) {
                        this.startLocation = this.handNode.position;
                        this.catchNode.dispatchEvent(this.getTouchEvent(cc.Node.EventType.TOUCH_START));
                    }
                }
            }
        });

        this.btn.addKeyUpEvent((para: KeyEventParameters) => {
            if (this.levelStop) return;
            if (isDirectionKey(para.DirectionCode)) {
                this.moveSpeed.moveSpeed = 0;
                if (this.catchNode) {
                    this.playHandCatchingAction();
                }
            }
            this.addBtnEventKeyUp(para);
        });

        this.btn.addFingerOutEvent((para: MoveInfo) => {
            this.onLoseFocus();
            if (this.catchNode) {
                this.btn.callKeyDownEvents(DirectionCode.ENTER, para.startLayout, false);
                this.setSiteByNode(this.firstNode);
                this.resetBtnPos();
            }
        });

        this.btn.addBeforeFingerInEvent((para: MoveInfo) => {
            this.onFocus();
        });

        this.handNode.on(cc.Node.EventType.POSITION_CHANGED, () => {
            triggerTouchMoveEvent();
        }, this);
    }

    private moveButton(direction: DirectionCode) {
        let oldSite = this.currSite.clone();
        switch (direction) {
            case DirectionCode.LEFT:
                if (oldSite.y > 0) {
                    oldSite.y--;
                    oldSite.x = Math.min(oldSite.x, this.nodeGrid.length - 1);
                }
                break;
            case DirectionCode.RIGHT:
                if (oldSite.y < this.nodeGrid[oldSite.x].length - 1) {
                    oldSite.y++;
                    oldSite.x = Math.min(oldSite.x, this.nodeGrid.length - 1);
                }
                break;
            case DirectionCode.UP:
                if (oldSite.x > 0) {
                    oldSite.x--;
                    oldSite.y = Math.min(oldSite.y, this.nodeGrid[oldSite.x].length - 1);
                }
                break;
            case DirectionCode.DOWN:
                if (oldSite.x < this.nodeGrid.length - 1) {
                    oldSite.x++;
                    oldSite.y = Math.min(oldSite.y, this.nodeGrid[oldSite.x].length - 1);
                }
                break;
        }
        if (!oldSite.equals(this.currSite)) {
            this.currSite = oldSite;
            this.resetBtnPos();
        }
    };

    protected resetBtnPos(offset: cc.Vec3 = cc.v3(8, -8)) {
        let currItem = this.nodeGrid[this.currSite.x][this.currSite.y];
        if ((this.items && this.items.find(item => item._view === currItem)) || this.catchNode) {
            this.btn.offset = cc.v3(this.nodeGrid[this.currSite.x][this.currSite.y].convertToWorldSpaceAR(cc.Vec3.ZERO).subtract(this.node.convertToWorldSpaceAR(cc.Vec3.ZERO))).add(offset);
            this.tscene.fingerStyle = FingerStyle.hand;
        } else {
            this.btn.offset = cc.v3(this.nodeGrid[this.currSite.x][this.currSite.y].convertToWorldSpaceAR(cc.Vec3.ZERO).subtract(this.node.convertToWorldSpaceAR(cc.Vec3.ZERO)));
            this.tscene.fingerStyle = FingerStyle.finger;
        }
    }

    protected setSiteByNode(firstNode: cc.Node) {
        this.nodeGrid.some((row: cc.Node[], i: number) => {
            return row.some((node: cc.Node, j: number) => {
                if (node === firstNode) {
                    this.firstNode = firstNode;
                    this.currSite = cc.v2(i, j);
                    return true;
                }
                return false;
            });
        });
    }

    protected addBtnEventKeyDown(para: KeyEventParameters) {
    }

    protected initActiveObject() {
    }
    protected addBtnEventKeyLongPress(para: KeyEventParameters, dt: number) {
    }
    protected addBtnEventKeyUp(para: KeyEventParameters) {
    }
}
